package com.hujifang.elasticsearch.utils;

import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * 拼音工具类<br/>
 * Created by Hurricane.Hu on 2016/7/23.
 */
public class Pinyin4jUtil {

	/**
	 * 拼音大写输出
	 * @param chinese
	 */
	public static Set<String> getPinyinToUpperCase(String chinese) {
		Set<String> stringSet=makeStringByStringSet(chinese);
		if(!StrUtil.isEmpty(stringSet)){
			Set<String> pinyinSet=new HashSet<>();
			for (String string:stringSet){
				pinyinSet.add(string.toUpperCase());
			}
			return pinyinSet;
		}
		return null;
	}

	/**
	 * 拼音小写输出
	 * @param chinese
	 */
	public static Set<String> getPinyinToLowerCase(String chinese) {
		Set<String> stringSet=makeStringByStringSet(chinese);
		if(!StrUtil.isEmpty(stringSet)){
			Set<String> pinyinSet=new HashSet<>();
			for (String string:stringSet){
				pinyinSet.add(string.toLowerCase());
			}
			return pinyinSet;
		}
		return null;
	}

	/**
	 * 首字母大写输出
	 * @param chinese
	 */
	public static Set<String> getPinyinFirstToUpperCase(String chinese) {
		return makeStringByStringSet(chinese);
	}

	/**
	 * 拼音简拼大写输出
	 * @param chinese
	 */
	public static Set<String> getPinyinJianPinToUpperCase(String chinese) {
		Set<String> pinyinSet=makeStringByStringSet(chinese);
		if(!StrUtil.isEmpty(pinyinSet)){
			Set<String> stringSet=new HashSet<>();
			for (String str : pinyinSet) {
				StringBuilder strChar =new StringBuilder();
				char chars[] = str.toCharArray(); // 将字符串转化成char型数组
				for (char ch:chars) {
					if (ch >=65 && ch <91) { // 判断是否是大写字母
						strChar.append(String.valueOf(ch));
					}
				}
				stringSet.add(strChar.toString());
			}
			return stringSet;
		}
		return null;
	}

	/**
	 * 拼音简拼小写输出
	 * @param chinese
	 */
	public static Set<String> getPinyinJianPinToLowerCase(String chinese) {
		Set<String> pinyinSet=makeStringByStringSet(chinese);
		if(!StrUtil.isEmpty(pinyinSet)){
			Set<String> stringSet=new HashSet<>();
			for (String str : pinyinSet) {
				StringBuilder strChar =new StringBuilder();
				char chars[] = str.toCharArray(); // 将字符串转化成char型数组
				for (char ch:chars) {
					if (ch >='A' && ch <='Z') { // 判断是否是大写字母
						strChar.append(String.valueOf(ch).toLowerCase());
					}
				}
				stringSet.add(strChar.toString());
			}
			return stringSet;
		}
		return null;
	}

	/**
	 * 字符集转换
	 * @param chinese
	 */
	public static Set<String> makeStringByStringSet(String chinese) {
		return makeStringByStringSet(chinese,10);
	}

	/**
	 * 字符集转换
	 * @param chinese
	 * @param lenLimit
	 */
	public static Set<String> makeStringByStringSet(String chinese,int lenLimit) {
		if(!StrUtil.isBlank(chinese) && chinese.length()<=lenLimit){
			char[] srcChar = chinese.toCharArray();
			HanyuPinyinOutputFormat defaultFormat=getDefaultOutputFormat();
			List<List<String>> tempList =new ArrayList<>();
			for (char c : srcChar) {
				// 是中文或者a-z或者A-Z转换拼音
				if (String.valueOf(c).matches("[\\u4E00-\\u9FA5]+")) {
					try {
						String[] temp = PinyinHelper.toHanyuPinyinStringArray(c, defaultFormat);
						tempList.add(Arrays.asList(temp));
					} catch (BadHanyuPinyinOutputFormatCombination e) {
						e.printStackTrace();
					}
				} else if ((c >='A' && c <='Z') || (c >='a' && c <='z')) {
					tempList.add(Collections.singletonList(String.valueOf(c)));
				}
			}
			List<String>  pinyinList=getPermutationSentence(tempList,0);
			Set<String> chinesePinyin = new HashSet<>();
			chinesePinyin.addAll(pinyinList);
			return chinesePinyin;
		}
		return null;
	}

	/**
	 * 多音字排列
	 * @param termArrays
	 * @param start
	 */
	public static List<String> getPermutationSentence(List<List<String>> termArrays,int start) {

		if (CollectionUtils.isEmpty(termArrays)){
			return Collections.emptyList();
		}
		int size = termArrays.size();
		if (start < 0 || start >= size) {
			return Collections.emptyList();
		}
		if (start == size - 1) {
			return termArrays.get(start);
		}

		List<String> strings = termArrays.get(start);

		List<String> permutationSentences = getPermutationSentence(termArrays, start + 1);

		List<String> result = new ArrayList<>();

		if (CollectionUtils.isEmpty(strings)) {
			for (String permutationSentence:permutationSentences){
				result.add(capitalize(permutationSentence));
			}
			return result;
		}
		if (CollectionUtils.isEmpty(permutationSentences)) {
			for (String string:strings){
				result.add(capitalize(string));
			}
			return strings;
		}
		for (String pre : strings) {
			for (String suffix : permutationSentences) {
				result.add(capitalize(pre)+capitalize(suffix));
			}
		}
		return result;
	}
	/**
	 * Default Format 默认输出格式
	 */
	public static HanyuPinyinOutputFormat getDefaultOutputFormat() {
		HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
		format.setCaseType(HanyuPinyinCaseType.LOWERCASE);// 小写
		format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);// 没有音调数字
		format.setVCharType(HanyuPinyinVCharType.WITH_U_AND_COLON);// u显示
		return format;
	}

	/**
	 * 首字母大写
	 * @param pinyinStr
	 */
	public static String capitalize(String pinyinStr) {
		char ch[]= pinyinStr.toCharArray();
		if (ch[0] >= 'a' && ch[0] <= 'z') {
			ch[0] = (char) (ch[0] - 32);
		}
		return new String(ch);
	}


	public static void main(String[] args) {
		String str = "重庆woshi";
		System.out.println("小写输出：" + getPinyinToLowerCase(str));
		System.out.println("大写输出：" + getPinyinToUpperCase(str));
		System.out.println("首字母大写输出：" + getPinyinFirstToUpperCase(str));
		System.out.println("简拼输出：" + getPinyinJianPinToUpperCase(str));
		System.out.println("简拼输出：" + getPinyinJianPinToLowerCase(str));
	}
}